﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ALDIOrganizer.Properties;

namespace ALDIOrganizer
{
    /// <summary>
    /// Stores Time of the Day as quarters
    /// </summary>
    [Serializable]    
    public struct TimeByQuarters : IComparable
    {
        /* Time of the Day stored as quarters -
         * for example, 16:30 = 4*16 + 2 [66] */
        private byte _time;
        public byte Time
        {
            get
            {
                return _time;
            }
            set
            {
                _time = (value > 95) ? (byte)95 : value;
            }
        }
                

        public TimeByQuarters(byte pTime)
            : this()
        {
            this.Time = pTime;
        }

        public TimeByQuarters? AsNullable()
        {
            return new TimeByQuarters?(this);
        }

        public int GetHour
        {
            get
            {
                return (this.Time >> 2); // >> 2 - Shift right by two bytes (quick /4)
            }
        } 

        public int GetMinutes
        {
            get
            {
                return ((this.Time & 3) * 15); // bit operations again...
            }        
        }

        public override string ToString()
        {
            return String.Concat(
                GetHour.ToString(),
                ":",
                GetMinutes.ToString("d2"));            
        } 
                
        /// <summary>
        /// Returns time string in 24h format (eg. 15:00)
        /// </summary>
        /// <param name="pFormat">
        /// Only "d2" accepted at the moment - could be customized in future
        /// if more formats were needed
        /// </param>        
        public string ToString(string pFormat)
        {
            string _result = string.Empty;
            if (pFormat == "d2")
            {
                _result += String.Concat(
                    GetHour.ToString("d2"),
                    ":",
                    this.GetMinutes.ToString("d2"));
            }
            return _result;
        }



        public static string GetDescriptiveString(TimeByQuarters? pStartHour, TimeByQuarters? pEndHour)
        {            
            var _howManyHaveValue = 0;
            if (pStartHour.HasValue)
            {
                _howManyHaveValue++;
            }
            if (pEndHour.HasValue)
            {
                _howManyHaveValue++;
            }
            if (_howManyHaveValue == 0)
            {
                return String.Empty;
            }

            var _result = String.Empty;
            var _hash = String.Empty;
            var _dolar = String.Empty;
            if (_howManyHaveValue == 1)
            {
                var _is_it_first_one = pStartHour.HasValue;
                if (_is_it_first_one)
                {
                    _result = Resources.RequestBindingField_AfterHour;
                    _hash = pStartHour.Value.ToString("d2");
                }
                else
                {
                    _result = Resources.RequestBindingField_BeforeHour;
                    _hash = pEndHour.Value.ToString("d2");
                }
            }
            if (_howManyHaveValue == 2)
            {
                _result = Resources.RequestBindingField_BetweenHours;
                _hash = pStartHour.Value.ToString("d2");
                _dolar = pEndHour.Value.ToString("d2");
            }
            
            _result = _result.Replace(
                "#",
                _hash);
            _result = _result.Replace(
                "$",
                _dolar);
            return _result;
        }

        public static KeyValuePair<bool, TimeByQuarters> Parse(String s)
        {            
            TimeByQuarters _result = default(TimeByQuarters);
            var valid = true;
            int _hour;
            int _minutes;
            try
            {
                if (s.Contains(":"))
                {
                    var _sides = s.Split(new char[] { ':' });
                    _hour = int.Parse(_sides[0]);
                    _minutes = (_sides[1].Trim() == String.Empty) ? 
                        0 : int.Parse(_sides[1]);
                }
                else
                {
                    _hour = int.Parse(s);
                    _minutes = 0;
                }
                if (_hour > 23 || _minutes > 60)
                {
                    throw new Exception();
                }
                _result.Time = (byte)((4 * _hour) + (_minutes / 15));
            }
            catch
            {
                valid = false;
                _result = default(TimeByQuarters);
            }
            return new KeyValuePair<bool,TimeByQuarters>(
                valid,
                _result);
        }

        public static bool operator ==(TimeByQuarters h1, TimeByQuarters h2)
        {
            return (h1.Time == h2.Time);
        }

        public static bool operator !=(TimeByQuarters h1, TimeByQuarters h2)
        {
            return (h1.Time != h2.Time);
        }

        public static bool operator <(TimeByQuarters h1, TimeByQuarters h2)
        {
            return h1.Time < h2.Time;
        }

        public static bool operator >(TimeByQuarters h1, TimeByQuarters h2)
        {
            return h1.Time > h2.Time;
        }

        #region IComparable Members

        public int CompareTo(object obj)
        {
            TimeByQuarters h = (TimeByQuarters)obj;
            return this.Time.CompareTo(h.Time);
        }

        #endregion

        public bool Equals(TimeByQuarters other)
        {
            return other.Time == Time;
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (obj.GetType() != typeof(TimeByQuarters)) return false;
            return Equals((TimeByQuarters)obj);
        }

        public override int GetHashCode()
        {
            return Time.GetHashCode();
        }
    }
}
